package com.wwm.springcloud.base.result;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import java.lang.reflect.Field;
import java.security.Key;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * Created by ljgsonx on 2016/1/23.
 */
public class StringUtil {
    
    /**
     * 常用字符串
     */
    private final static String EMPTYSTR = "";
    
    private static final char[] hexStrings = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
            'e', 'f' };

    private static final char[] chars = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
            'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
            'V', 'W', 'X', 'Y', 'Z' };
    
    /**
     * 匹配数字
     */
    private static String PATTERN_NUMBER = "^[0-9]*$";
    
    public static boolean isMatchRegex(String matchString, String regexString) {
        boolean flag = false;
        if (!isBlank(matchString)) {
            Pattern pattern = Pattern.compile(regexString);
            Matcher matcher = pattern.matcher(matchString);
            flag = matcher.matches();
            pattern = null;
            matcher = null;
        }
        matchString = null;
        return flag;
    }

    public static boolean isNumber(String numberStr) {
        return isMatchRegex(numberStr, PATTERN_NUMBER);
    }

    
    /**
     * Description: <p>判断字符串是否为null,或是否为空字符串</p>
     * <p>null或空字符串:true</p>
     * Author: ljgsonx
     * Time: 2016/1/23 12:07
     */
    public static boolean isBlank(String str){
        if(str == null)
            return true;
        str = str.trim();
        if("".equals(str))
            return true;
        return false;
    }

    public static boolean isNotBlank(String str) {
        return (str != null && str.trim().length() > 0);
    }

    /**
     * Description: 判断传进来的所有参数,是否有null或有空字符串
     * Author: ljgsonx
     * Time: 2016/1/23 18:13
     */
    public static boolean hasBlank(String... str){
        for(String s:str){
            if(isBlank(s)){
                return true;
            }
        }
        return false;
    }
    
    /**
     * 返回不带null键值的json字符串
     * 
      * @author liujingui
      * @param o
      * @return String  
      * @date 2016年3月18日 下午2:48:56
     */
    public static String getJSONDefault(Object o){
        return JSONObject.toJSONString(o);
    }
    
    /**
     * 返回带null键值的json字符串
     * 
      * @author liujingui
      * @param o
      * @return String  
      * @date 2016年3月18日 下午2:48:56
     */
	public static String getJSON(Object o){
		return JSONObject.toJSONString(o, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);
	}
	
    /**
     * 返回带日期,并格式化的json字符串
     * 
      * @author liujingui
      * @param o
      * @return String  
      * @date 2016年3月18日 下午2:48:56
     */
	public static String getJSONWithDate(Object o){
		return JSONObject.toJSONStringWithDateFormat(o, "yyyy-MM-dd", SerializerFeature.WriteDateUseDateFormat);
	}
	
    /**
     * 以SHA-1算法加密字符串,返回十六进制字符串
     * 
     * @author liujingui
     * @param Str
     *            原字符串
     * @param isUpperCase
     *            返回的十六进制字符串字母是否大写
     * @return String 加密后字符串
     * @date 2015年10月17日 下午1:43:21
     */
    public static String hashCode(String Str, boolean isUpperCase) {
        if (isUpperCase) {
            return hashCode(Str, "SHA-1").toUpperCase();
        } else {
            return hashCode(Str, "SHA-1");
        }
    }
    
    /**
     * 将字符串加密,并转大写16进制字符串返回
     * 
     * @author liujingui
     * @param str
     *            原字符串
     * @param algorithm
     *            加密算法
     * @return String 加密后字符串
     * @date 2015年10月17日 下午4:35:51
     */
    public static String hashCode(String str, String algorithm) {

        if (str == null)
            return EMPTYSTR;

        return toHexString(digest(str, algorithm));

    }
    
    /**
     * 将一个字节数组转换成十六进制字符串
     * 
     * @author liujingui
     * @param b
     *            字节数组
     * @return String 十六进制字符串
     * @date 2015年10月19日 下午1:53:11
     */
    public static String toHexString(byte b[]) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            hexString.append(byteHEX(b[i]));

        return hexString.toString();
    }
    
    /**
     * 将一个字节转换成十六进制字符串的数组,效率优于Integer.toHexString(),不需要再判断位数,来决定是否加0
     * 
     * @author liujingui
     * @param ib
     *            一个字节
     * @return char[] 一个字节的十六进制字符串数组
     * @date 2015年10月19日 下午1:51:49
     */
    public static char[] byteHEX(byte ib) {
        char[] ob = new char[2];
        ob[0] = hexStrings[(ib >>> 4) & 0X0F];
        ob[1] = hexStrings[ib & 0X0F];
        return ob;
    }
    
    /**
     * MessageDigest.getInstance(String algorithm); Param algorithm, the name of
     * the algorithm requested.(MD5,SHA-1,SHA-256,etc...)
     */
    public static byte[] digest(String str, String algorithm) {
        try {
            MessageDigest digest = MessageDigest.getInstance(algorithm);
            digest.update(str.getBytes());
            return digest.digest();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new byte[0];
    }
    
    /**
     * 对字符串数组各元素根据首字母进行排序,并返回所有元素拼接后字符串
     * 
     * @author liujingui
     * @param strings
     *            任意长度字符串数组
     * @return String
     * @date 2015年10月17日 下午2:01:01
     */
    public static String sortString(String... strings) {

        StringBuffer sb = new StringBuffer();
        // 字符串排序
        Arrays.sort(strings);
        for (int i = 0; i < strings.length; i++) {
            sb.append(strings[i]);
        }
        return sb.toString();
    }
    
    /**
     * 生成5-9位的随机字符串
     * 
     * @author liujingui
     * @return String 5-9位的随机字符串
     * @date 2015年10月15日 上午11:42:12
     */
    public static String getRandomString() {
        Random random = new Random();
        int length = 5 + random.nextInt(5);
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(chars.length);
            sb.append(chars[number]);
        }
        return sb.toString();
    }

    /**
     * 通过反射获取传进来对象的数据,拼装成key1=value1&key2=value2形式的字符串
     *  (传进来的对象字段只能为String,float,double,int,boolean)
      * @author liujingui
      * @param o
      * @return String  
      * @date 2016年3月15日 下午4:54:23
     */
    public static String getKeyValueStr(Object o){
        StringBuffer sb = new StringBuffer();
        try{
            Field[] fields = o.getClass().getDeclaredFields();
            for(int i =0;i<fields.length;i++){
                fields[i].setAccessible(true);
                Object value = fields[i].get(o);
                if(value instanceof String){
                    if(!StringUtil.isBlank((String)value)){
                        sb.append(fields[i].getName()+"="+value+"&");
                    } 
                }else if(value instanceof Integer){
                    sb.append(fields[i].getName()+"="+(int)value+"&");
                }else if(value instanceof Float){
                    sb.append(fields[i].getName()+"="+(float)value+"&");
                }else if(value instanceof Double){
                    sb.append(fields[i].getName()+"="+(double)value+"&");
                }else if(value instanceof Boolean){
                    sb.append(fields[i].getName()+"="+(boolean)value+"&");
                }else if(value == null){
                    // do nothing... ignroed this property
                }else{
                    throw new IllegalArgumentException("the property of object only can be one of String,Integer,Float,Double,Boolean");
                }
            }
            if(sb.charAt(sb.length()-1) == '&'){
                sb.deleteCharAt(sb.length()-1);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        
        return sb.toString();
    }
    
    /** 
     * 二进制转字符串 
     * @param b byte数组 
     * @return 二进制字符串 
     */  
    public static String byte2hex(byte[] b){
        if(b == null) return "";
        StringBuffer sb = new StringBuffer();  
        String stmp = "";  
        for (int n = 0; n < b.length; n++) {  
            stmp = Integer.toHexString(b[n] & 0XFF);  
            if (stmp.length() == 1) {  
                sb.append("0" + stmp);  
            } else {  
                sb.append(stmp);  
            }  
        }  
        return sb.toString();  
    }
    
    /** 
     * 字符串转二进制 
     * @param str 字符串 
     * @return byte数组 
     */  
    public static byte[] hex2byte(String str) {  
        if (str == null)  
            return null;  
        str = str.trim();  
        int len = str.length();  
        if (len == 0 || len % 2 == 1)  
            return null;  
        byte[] b = new byte[len / 2];  
        try {  
            for (int i = 0; i < str.length(); i += 2) {  
                b[i / 2] = (byte) Integer.decode("0X" + str.substring(i, i + 2)).intValue();  
            }  
            return b;  
        } catch (Exception e) {  
            return null;  
        }  
    }
    
    private static byte[] des3EncodeECB(byte[] key, byte[] data)  
            throws Exception {  
        Key deskey = null;  
        DESedeKeySpec spec = new DESedeKeySpec(key);  
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");  
        deskey = keyfactory.generateSecret(spec);  
        Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");  
        cipher.init(Cipher.ENCRYPT_MODE, deskey);  
        byte[] bOut = cipher.doFinal(data);  
        return bOut;  
    }
    
    /** 
     * ECB解密,不要IV 
     * @param key 密钥 
     * @param data Base64编码的密文 
     * @return 明文 
     * @throws Exception 
     */  
    private static byte[] des3DecodeECB(byte[] key, byte[] data)  
            throws Exception {  
        Key deskey = null;  
        DESedeKeySpec spec = new DESedeKeySpec(key);  
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");  
        deskey = keyfactory.generateSecret(spec);  
        Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");  
        cipher.init(Cipher.DECRYPT_MODE, deskey);  
        byte[] bOut = cipher.doFinal(data);  
        return bOut;  
    }
    
    /**
     * des3加密算法
     * 
      * @author liujingui
      * @param key 秘钥
      * @param value 源字符串
      * @return String  加密后字符串
      * @date 2016年4月21日 上午11:02:28
     */
    public static String des3Encode(String key,String value){
       byte[] outPutBytes = null;
       try{
           outPutBytes = des3EncodeECB(key.getBytes("UTF-8"), value.getBytes());
       }catch(Exception e){
           e.printStackTrace();
       }
       return byte2hex(outPutBytes);
    }
    
    /**
     * des3解密算法
     * 
      * @author liujingui
      * @param key 秘钥
      * @param value 源加密的字符串
      * @return String  解密后字符串
      * @date 2016年4月21日 上午11:02:28
     */
    public static String des3Decode(String key,String value){
        byte[] outPutBytes = null;
        try{
            outPutBytes = des3DecodeECB(key.getBytes("UTF-8"), hex2byte(value));
        }catch(Exception e){
            e.printStackTrace();
        }
        return new String(outPutBytes);
    }
    
    /**
	  * @author wsdoing
	  * @Description: 获取云平台请求报文
	  * @param @param nsrsbh
	  * @param @param jrdm
	  * @param @param kpXml
	  * @param @return  
	  * @return String  
	  * @throws
	  * @date 2016年12月7日 下午1:39:08
	 */
	public static String getXml(String nsrsbh , String jrdm , String fwdm ,String xml){
		return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
				"<fwpackage>"+
					"<jsnr>"+
						"<fwdm>"+fwdm+"</fwdm>"+
						"<nsrsbh>"+nsrsbh+"</nsrsbh>"+
						"<jrdm>"+jrdm+"</jrdm>"+
					"</jsnr>"+
					"<ywnr><![CDATA["+xml+"]]></ywnr>"+
				"</fwpackage>";
	}
	
	public static String getInvoiceXml(String jr_nsrsbh,String kp_nsrsbh, String fpqqlsh, String ghdwmc, String ghdwdm,
			String ghdwdzdh,String ghdwyhzh , String dh , String yx){
		
		return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + 
				"<fwpackage>\r\n" + 
				"	<jsnr>\r\n" + 
				"		<fwdm>1031</fwdm>\r\n" + 
				"		<nsrsbh>"+jr_nsrsbh+"</nsrsbh>\r\n" + 
				"	</jsnr>\r\n" + 
				"	<ywnr><![CDATA[<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + 
				"		<request>\r\n" + 
				"			<nsrsbh>"+kp_nsrsbh+"</nsrsbh>\r\n" + 
				"			<fpqqlsh>"+fpqqlsh+"</fpqqlsh>\r\n" + 
				"			<ghdwmc>"+ghdwmc+"</ghdwmc>\r\n" + 
				"			<ghdwdm>"+(ghdwdm==null?"":ghdwdm.trim())+"</ghdwdm>\r\n" + 
				"			<ghdwdzdh>"+(ghdwdzdh==null?"":ghdwdzdh.trim())+"</ghdwdzdh>\r\n" + 
				"			<ghdwyhzh>"+(ghdwyhzh==null?"":ghdwyhzh.trim())+"</ghdwyhzh>\r\n" + 
				"			<dh>"+(dh==null?"":dh.trim())+"</dh>\r\n" + 
				"			<yx>"+(yx==null?"":yx.trim())+"</yx>\r\n" +
				"			<tsqdbz>2</tsqdbz>\r\n"+
				"		</request>]]></ywnr>\r\n" + 
				"</fwpackage>";
	}
    /**
     * 获得系统时间前n天的时间点
     * @author qiaoyongda
     * @date 2017年01月19日 下午15:26:11
     */
    public static Date calendarDay(Integer n) {
		Calendar curr = Calendar.getInstance();			
		curr.set(Calendar.DAY_OF_MONTH,curr.get(Calendar.DAY_OF_MONTH)-n);		
		return curr.getTime();
    }
    
    /**
     * 获得系统时间前n月的时间点
     * @author qiaoyongda
     * @return String 十六进制字符串
     * @date 2017年01月19日 下午15:26:11
     */
    public static Date calendarMonth(Integer n) {
		Calendar curr = Calendar.getInstance();			
		curr.set(Calendar.MONTH,curr.get(Calendar.MONTH)-n);	
		return curr.getTime();
    }
    
    /**
     * 获得系统时间前n年的时间点
     * @author qiaoyongda   
     * @date 2017年01月19日 下午15:26:11
     */
    public static Date calendarYear(Integer n) {
		Calendar curr = Calendar.getInstance();			
		curr.set(Calendar.YEAR,curr.get(Calendar.YEAR)-n);	
		return curr.getTime();
    }

    public static String getUTCTime(Date date){
        SimpleDateFormat UTCFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        return UTCFormat.format(date);
    }
    public static boolean isEmpty(String s)
    {
        return ((s == null) ? true : s.trim().isEmpty());
    }
    /**
     * 得到非空的字符串，若字符串对象为null，则返回""。
     * @param objValue Object待转换的原字符串对象
     * @return String 转换后的字符串
     * */
    public static String objectToString(Object objValue){
        return (objValue == null ? "" : objValue.toString());
    }
}
